package com.cloudkinto.common.utils;

import cn.afterturn.easypoi.csv.CsvExportUtil;
import cn.afterturn.easypoi.csv.entity.CsvExportParams;
import cn.afterturn.easypoi.excel.annotation.Excel;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * Author Administrator
 *
 * @Des
 * @Version
 * @Date 2020/7/23
 */
public class CsvUtils {

    public static void exportCsv(CsvExportParams exportParams, Class<?> classType, List<?> data, String fileName, HttpServletResponse response) {
        try {
            response.setCharacterEncoding("Shift-JIS");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Access-Control-Expose-Headers","Content-Disposition");
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName, "UTF-8"));
            CsvExportUtil.exportCsv(exportParams, classType, data, response.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void exportCsv(CsvExportParams exportParams, Class<?> classType, List<?> data, ByteArrayOutputStream bos) {
        CsvExportUtil.exportCsv(exportParams, classType, data, bos);
    }

    public static void exportCsv(CsvExportParams exportParams, Class<?> classType, List<?> data, String fileName, String filePathTemp) {
        File file = new File(filePathTemp + File.separator + fileName);
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return;
        }
        CsvExportUtil.exportCsv(exportParams, classType, data, fileOutputStream);
    }


    public static void initCsv(String filePath, CsvExportParams params, Class<?> clazz) throws IOException {
        File file = new File(filePath);
        File parent = file.getParentFile();
        if (!parent.exists()) {
            parent.mkdirs();
        }

        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), params.getEncoding()))) {
            writer.write('\uFEFF');
            // 获取类的所有字段
            Field[] fields = clazz.getDeclaredFields();

            // 构建表头
            StringBuilder header = new StringBuilder();
            for (Field field : fields) {
                if (header.length() > 0) {
                    header.append(",");
                }
                Excel annotation = field.getAnnotation(Excel.class);
                String annotationName = annotation.name();
                header.append(StringUtils.isBlank(annotationName) ? field.getName() : annotationName);
            }

            // 写入表头
            writer.write(header.toString());
            writer.newLine();
        }
    }

    /**
     * 追加数据到CSV文件
     */
    public static void appendToCsv(String filePath, List<?> dataList) throws IOException {
        if (dataList == null || dataList.isEmpty()) {
            return;
        }

        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(filePath, true), StandardCharsets.UTF_8))) {

            for (Object obj : dataList) {
                writer.write(convertToCsvLine(obj));
                writer.newLine();
            }
        }
    }

    /**
     * 将对象转换为CSV行
     */
    private static String convertToCsvLine(Object obj) throws IOException {
        if (obj == null) {
            return "";
        }

        StringBuilder line = new StringBuilder();
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            field.setAccessible(true);

            try {
                Object value = field.get(obj);
                if (value != null) {
                    String strValue = value.toString();
                    // 处理包含逗号的值，用双引号包裹
                    if (strValue.contains(",")) {
                        strValue = "\"" + strValue.replace("\"", "\"\"") + "\"";
                    }
                    line.append(strValue);
                }

                // 不是最后一个字段时添加逗号
                if (i < fields.length - 1) {
                    line.append(",");
                }
            } catch (IllegalAccessException e) {
                throw new IOException("Error accessing field: " + field.getName(), e);
            }
        }

        return line.toString();
    }

    /**
     * 将CSV文件内容写入响应输出流
     */
    public static void writeCsvToResponse(String filePath, HttpServletResponse response) throws IOException {
        try (InputStream is = new FileInputStream(filePath);
             OutputStream os = response.getOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }

            os.flush();
        }
    }
}
